package tr.edu.metu.is.mega.client.course.admin;

import java.util.ArrayList;
import java.util.List;

import tr.edu.metu.is.mega.client.core.DialogCallbackAdapter;
import tr.edu.metu.is.mega.client.core.MainWindow;
import tr.edu.metu.is.mega.client.core.MegaToolbar;
import tr.edu.metu.is.mega.client.core.MegaUtil;
import tr.edu.metu.is.mega.client.resource.MEGAResourceBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.client.service.GwtCourseService;
import tr.edu.metu.is.mega.client.service.GwtCourseServiceAsync;
import tr.edu.metu.is.mega.common.dto.CourseDTO;

import com.extjs.gxt.ui.client.binding.FormBinding;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.FillLayout;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;

/**
 * Window for defining and changing course records.
 */
public class CourseManagementWindow extends MainWindow {

    private FormPanel gridPanel;

    private FormBinding formBindings;

    private Grid<BeanModel> grid;

    private final GwtCourseServiceAsync service;

    private final MEGAResourceBundle resourceBundle = MEGAResources.RESOURCEBUNDLE;

    /**
     * Default constructor.
     * 
     * @param featureIdentifier
     * @param className
     */
    public CourseManagementWindow() {
        super("CourseManagementWindow", CourseDTO.class.getName());
        service = GwtCourseService.Util.getInstance();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onRender(Element parent, int pos) {
        super.onRender(parent, pos);
        setHeading(resourceBundle.courseDefinitionManagementHeader());
        setLayout(new FillLayout());
        setHeight(600);

        gridPanel = new FormPanel();
        gridPanel.setPadding(0);
        gridPanel.setHeaderVisible(false);

        gridPanel.add(getGrid());

        gridPanel.setTopComponent(getToolBar());

        add(gridPanel);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void afterRender() {
        super.afterRender();
    }

    /**
     * Returns activity grid.
     * 
     * @return grid
     */
    private Widget getGrid() {
        if (grid == null) {

            // proxy and reader
            RpcProxy<List<CourseDTO>> proxy = new RpcProxy<List<CourseDTO>>() {

                @Override
                public void load(Object loadConfig, AsyncCallback<List<CourseDTO>> callback) {
                    CourseDTO dto = new CourseDTO();
                    service.getCourses(dto, callback);
                }
            };
            BeanModelReader reader = new BeanModelReader();

            ListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, reader);
            ListStore<BeanModel> store = new ListStore<BeanModel>(loader);

            loader.load();

            List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
            columns.add(new ColumnConfig(CourseDTO.FIELD_CODE, resourceBundle.courseCode(), 150));
            columns.add(new ColumnConfig(CourseDTO.FIELD_NAME, resourceBundle.courseName(), 150));
            columns.add(new ColumnConfig(CourseDTO.FIELD_SEMESTER, resourceBundle.courseSemester(), 150));
            columns.add(new ColumnConfig(CourseDTO.FIELD_INSTRUCTOR_NAME, resourceBundle.courseInstructor(), 150));
            columns.add(new ColumnConfig(CourseDTO.FIELD_ASSISTANTS, resourceBundle.courseAssistants(), 150));

            ColumnModel cm = new ColumnModel(columns);

            grid = new Grid<BeanModel>(store, cm);

            formBindings = new FormBinding(gridPanel, true);
            formBindings.bind(getNewModelData());

            MegaUtil.decoradeGridViewWithAutoHeight(grid, true);
        }
        return grid;
    }

    /**
     * @return returns empty modeldata
     */
    private ModelData getNewModelData() {
        CourseDTO dto = new CourseDTO();
        BeanModelFactory factory = BeanModelLookup.get().getFactory(CourseDTO.class);
        BeanModel model = factory.createModel(dto);
        return model;
    }

    /**
     * Initializes and returns toolbar.
     * 
     * @return toolbar
     */
    private Component getToolBar() {
        MegaToolbar toolbar = new MegaToolbar(true, true, true);

        toolbar.setUpdateListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    CourseDTO dto = grid.getSelectionModel().getSelectedItem().getBean();
                    CourseDefinitionDialog definitionDialog = new CourseDefinitionDialog();
                    definitionDialog.update(dto, new DialogCallbackAdapter<CourseDTO>() {

                        @Override
                        public void onOk(CourseDTO param) {
                            service.updateCourse(param, new AsyncCallback<CourseDTO>() {

                                @Override
                                public void onFailure(Throwable caught) {
                                }

                                @Override
                                public void onSuccess(CourseDTO result) {
                                    grid.getStore().getLoader().load();
                                }
                            });
                        }
                    });
                }

            }
        });

        toolbar.setInsertListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                CourseDTO dto = new CourseDTO();
                CourseDefinitionDialog definitionDialog = new CourseDefinitionDialog();
                definitionDialog.create(dto, new DialogCallbackAdapter<CourseDTO>() {

                    @Override
                    public void onOk(CourseDTO param) {
                        service.createCourse(param, new AsyncCallback<CourseDTO>() {

                            @Override
                            public void onFailure(Throwable caught) {
                            }

                            @Override
                            public void onSuccess(CourseDTO result) {
                                grid.getStore().getLoader().load();
                            }
                        });
                    }
                });

            }
        });

        toolbar.setDeleteListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    CourseDTO dto = grid.getSelectionModel().getSelectedItem().getBean();
                    // Delete calismiyor.
                    service.deleteCourse(dto, new AsyncCallback<Void>() {

                        @Override
                        public void onFailure(Throwable caught) {
                        }

                        @Override
                        public void onSuccess(Void result) {
                            grid.getStore().getLoader().load();
                        }
                    });
                }
            }
        });

        return toolbar;
    }
}
